﻿using System;
using System.Reflection;

namespace SAP.BusinessOne.WebBridge.Framework
{
    public class Proxy
    {
        private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
        private static readonly ObjectCache Cache = new ObjectCache(Assembly.GetExecutingAssembly());

        public static int Create(string args)
        {
            Args p = null;

            try
            {
                p = new Args(args);

                // get type name
                string type;
                p.Get(out type);

                // create target object
                var hash = Cache.CreateObject(type);

                // return true with object hash code
                p.Put(true).Put(hash);
            }
            catch (Exception e)
            {
                Log.Error("Failed to create instance", e);
                if (p != null)
                {
                    // return false with error message
                    p.Put(false).PutString(e.Message);
                }
            }

            return 0;
        }

        public static int Invoke(string args)
        {
            Args p = null;

            try
            {
                p = new Args(args);

                // get type name, hash, method
                string type, method;
                int hash;
                p.Get(out type).Get(out hash).Get(out method);

                // find the object from cache
                var target = Cache.GetObject(type, hash);

                // find the method info as well as parameters
                var mm = Cache.GetMethod(type, method);

                // prepare the prameters
                var objs = InteropUtil.EncapsulateParameterList(p, mm.Item2);

                // invoke the method
                var ret = mm.Item1.Invoke(target, objs);

                // return true
                p.Put(true);

                // return the data
                InteropUtil.PutReturnData(p, mm.Item3, ret);
            }
            catch (Exception e)
            {
                Log.Error("Failed to invoke method", e);
                if (p != null)
                {
                    // return false with error message
                    p.Put(false).PutString(e.Message);
                }
            }

            return 0;
        }
    }
}
